{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import os\n",
    "os.chdir(\"/home/lab466/pythons/pyLearnDM35/ch08\")\n",
    "import numpy as np\n",
    "from PIL import Image, ImageDraw, ImageFont\n",
    "from skimage import transform as tf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def create_captcha(text, shear=0, size=(100,24)):\n",
    "    im = Image.new(\"L\", size, \"black\")\n",
    "    draw = ImageDraw.Draw(im)\n",
    "    font = ImageFont.truetype(r\"Coval.otf\", 22)\n",
    "    draw.text((2, 2), text, fill=1, font=font)\n",
    "    image = np.array(im)\n",
    "    affine_tf = tf.AffineTransform(shear=shear)\n",
    "    image = tf.warp(image, affine_tf)\n",
    "    return image / image.max()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f4a700daba8>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f4a744ddc88>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "from matplotlib import pyplot as plt\n",
    "image = create_captcha(\"GENE\", shear=0.5)\n",
    "plt.imshow(image, cmap=\"gray\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from skimage.measure import label, regionprops\n",
    "\n",
    "def segment_image(image):\n",
    "    labeled_image = label(image > 0)\n",
    "    subimages = []\n",
    "    for region in regionprops(labeled_image):\n",
    "        start_x, start_y, end_x, end_y = region.bbox\n",
    "        subimages.append(image[start_x:end_x, start_y:end_y])\n",
    "    if len(subimages) == 0:\n",
    "        return [image,]\n",
    "    return subimages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlAAAAB/CAYAAAAgh/yPAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAEfZJREFUeJzt3X+MFEWfx/HPV1lY4A+yrj5xfSQoGvAPgxiWR0UTlUSi\nHHqeaLI5FfOowWBMzqiXKEbUBIhnNHqJkUCUnBpzEsXHqKc5FT0TNAoLAURB7wiSw8gJAuofsPij\n7o+diStbNWz11nRPz7xfCWGo7umqanqqv11V3W3OOQEAAGDojiu6AAAAAGVDAAUAABCJAAoAACAS\nARQAAEAkAigAAIBIBFAAAACRCKAAAAAiEUABAABEIoACAACINKLeGZhZpkedt7e3e9NPO+204RQn\nmUOHDgWX7dq1K8eShIX2oZR+P27fvn2fc+6kpBsFAKBBRQdQZtYu6RVJ4yVtkTTP1eF9MKET/MqV\nK1Nnlcm2bduCy2655ZYcSxJWK0hKvR9nzJjRGFEjAAA5yDKEd4Ok3c65cyR1SLosbZEAAAAaW5Yh\nvJmSVlc+vy/pUknvJCsRWkJsT+aIESNcW1vboPRGGdItUmg4OctQcpFD599++60OHjxodc8IGIC2\nKJ2UbVHRnHPHbIuyBFCdkn6ofP5R0uSjVzCz+ZLmZ9g2Wke1J3OOmb2p/p7MYCDe1tbmbaAaZUi3\nSKHh5CxDyUUOnd988811zwPwoC1KJGVbVAZZhvD2SRpX+Tyu8u8/cM6tcM51O+e6h1M4NLWZkt6t\nfK72ZAJA3miLkEmWAGqNpFmVzzMlfZCuOGghR/dknnD0CmY238x6zaz3l19+ybVwAFoGbREyyTKE\n96Kka8xsi6TN6g+oMrnvvvuCy6ZMmeJNP/3004PfOfnkk7MWJdoFF1wQXDZx4sTgsj179gSXLVmy\nxJu+devWoRdsgO3btweX/fTTT970WbNmedPrYEg9mZJWSNLo0aOT3+mJ8ouZv1LE3JUi5oSkmsfm\nK3uqctdzrl2GR6rQFiGT6ADKOdcnaU4dyoLWUu3JXK3+nswnaq18+PBhb0AYCgSlXIPBQoWC+VWr\nVnnT33knfM9HKOjOYz+PHTs2y9eGPH+liLkrRcwJSTWPzVf2VOWu51y7DI9UoS1KJGVbVAY8iRxF\neVHSnys9mfs1jJ5MtDTmr2C4aIuQSd2fRA740JOJRGreFTzwjuARI2juMBhtEbKiBwpAmdWcvzLw\njmACKAApEUABKDPuCgZQCC7JAJTZkO8Kjp38m2LibxGTamNvBAjV01f2VOWOKWOrTMBG+dQ9gBo5\ncqROOeUU77Kzzz47+L2enp56FanuLrnkkkzf6+rqSrq9WpYuXepNp7FCmTB/BUBR6IFCqYUCQal1\ngsGdO3d60zs7O5PlwX4GauM3kk9b1EiYAwUAABCJAAoAACASARQAAEAk5kABaGlF3FDxzDPPeNMX\nL148KG3FihVJ8kxRz4ULF3rTU72Sw1fGVpk/hPKpewA1ZswYTZ061bvsvPPOS5rXa6+9FlxW6yW+\njeLqq6/2pl944YXB73z00UeZ8vrwww+96WvXrg1+56KLLsqUFwAAzYYeKJRaKBCUwsFglkCwjMH5\nunXrkm0rr/0MlBVtUVjKtqiRMAcKAAAgEgEUAABAJIbwALS0mPmAqYYlx48f701fvnz5oLTPP//c\nu27s/MfYeY++ul588cXedUPzNFOUkSFiNCp6oAAAACIRQAEAAESq+xDeb7/9pr6+Pu+yM844I3p7\ne/fuDS777LPPgssWLVoUnVfenn32WW/6VVddFfxO1scYhNR6n9Nbb72VNC8AAMqKOVBoWqFgMEsg\nOGrUqOCyBQsWRG+vmaTcz0Azoi1qTgzhAQAARKIHCgA8fL0GRfSqPfnkk970UG9Db29v1PZT9I7c\nf//93vTZs2dHlcWHHk40KnqgAAAAIhFAAQAARCKAAgAAiJRpDpSZXS7pGUlfV5Jucc596Vv38OHD\n2rZtm3c727dvD+Zx1llnedNPOumk4HdeffXV4LIyCM1diJ3TMBxvv/12cNmmTZtyK0cKobrUqsfU\nqVO96VdccUX0d8q2v7JKuZ+BZkRb1JyG0wO1zDl3UeWPN3gCQszscjPbbWZrK38mF10mAK2HtghZ\nDecuvLlm9veS/lfStc45l6hMaB3LnHNLii4EyiumNzyWr9cgdCUf26O2c+dOb3pXV9egtO7ubu+6\n69ev96afe+653vRQ2WN6R2J7RVL0iGTpvcmAtgjRsvZA7ZD0gHPuL5K6JPnfMAnUNtfM1pnZajOz\noguD0qI3HMNFW4RoWQOo/ZLeq3z+WtKfBi40s/lm1mtmvb/++uswiocmdswgfOBxlHvpUCac/DAc\ntEXIJGsAdZekHjM7TtLZkrYOXOicW+Gc63bOdR9//PHDLSOaU80gXPrjcZRnwVAqNU9+nPgwBLRF\nyCRrAPWUpL9K+lTS35xzX6QrElpEzSAcGKKaJz9OfBgC2iJkkmkSuXPuW0mXDGXdsWPHBidBhh5V\nkFXodQKSdN111yXNqxUtWZJ0juVTkv5d0h3KOQivVY+XX345ensPPvigN/3666+P3lYeag2r9/X1\nJcsn9X4OuEvSV2b2gvpPfotTbRgtg7aoIHm1RfXCu/BQiJggHKgh15Nf6IQXe7LbsGGDN33VqlXD\n3nboJNrT0+NND52ofHWNLUvoojbFBW2qCzraImRFAAWgtDj5ASgKr3IBAACIRAAFAAAQiQAKAAAg\nktX7DSxmFszgyy/DDw2eNGlS0nJMnhx+vdFXX32VNK8WtaGet4rXOo5SCh2TWY7HAwcOeNMb+eGy\n559/vjd9x44dSfPx7edrrrlGW7durduDMNvb292pp546KD1F3VIdN7526o033kiy7dDxOH36dG+6\nb7/Us55Ssra4rm1Re3u7mzBhwqD01OcR2qJ82qIQ59wx2yJ6oAAAACIRQAEAAEQigAIAAIhEAAUA\nABCJAAoAACASTyIHBgi9HuK5556L3lZHR8dwi5O7RYsWedNvuummpPn49vOePXuS5nG0rq4ub/1S\n1C3VceN79cmMGTO8695xxx3e9IceesibHjoeY/7P61nPUJ6Npqury1v+PH4jEm1RIx0jhQZQtd5l\nlOUgqaXWi4Yb6T8EAAA0PobwAAAAIhFAAQAARCKAAgAAiEQABQAAEIm78AC0hIMHD+r1118flD56\n9Gjv+ocOHRrytp9//nlveuhGGd87+SRp3rx5g9IWLlzoXffhhx/2pt96663DzlOSTjzxxEFpN954\no3fd3bt3J8nTV9dvvvnGuy5QNAIolMLEiRP16KOPDkqfP39+8Dv79++Pzif2RCiFTxJZ3Hbbbd70\n77//PlkeWYSCDCku0KgK7Weg0XV2dkYFulK2IJC2yC91WzQchQZQtRrR2Cu3Ywld8UjhA78eVz7L\nly8PLuvs7EyeX0go8MgSdAAA0GqYAwUAABCJAAoAACASARQAAEAkJpEDKA0za5P0qnPuSjNrl/SK\npPGStkia55xzoe8ePHhQq1evzqmk/ZYuXepNf/rpp4e8jdBrqG6//XZv+pw5c7zpDzzwgDd97ty5\n3vTZs2cPSlu8eLF33RT1lPx1DdUTKBoBFEqho6PD29B/9913we+kbHhDJwgp/iTx8ccfB5ft2LHD\nm75mzZqoPJqRmY2W9KmkSZWkGyTtds7NMbM3JV0m6Z2iyofWVut9q7RFzYkhPOTGzNrM7I3K53Yz\ne9PMNpvZC2ZmRZcPjc05d8g5N0VS9aFDMyW9W/n8vqRLCykYSoe2CCkMqQdqON3mWaXqEh6K2C7y\n4di0aVNwWT3qFhLqualXdzm9B6iDTkk/VD7/KGny0SuY2XxJ4YeFoeXQFiGVY/ZAVQ62Deo/qKTf\nD7ZzJHUMSAeC6D1AHeyTNK7yeVzl33/gnFvhnOt2znXnWjI0LNoipHLMAIqDDXVydO/BCUevYGbz\nzazXzHr37t2ba+FQCmskzap8ninpgwLLgvKiLUImWSaR022OFIbUeyBphSR1d3cnHyZG6b0o6Roz\n2yJps/oDqoaybNkyb3roTQsdHR2D0hYsWOBdNzT1YPPmzd70a6+91pv+yCOPeNPvvPPOIZfl3nvv\n9aaHXq0Reh2Hb/uheh44cMCbngFtETLJMomcbnOkQO8BMnHOnVn5u885N8c5N8U5d2M95mKiJdAW\nIZMsPVDVg221+g+2J5KWCK0iSe9B6IpYSnvlGupJkOJ6EyRpxowZwW1t3LgxrmAAhou2yIO26Niy\nBFAN322OxjWw90CS/4l/AFBntEUYriEHUHkfbKEoe8KECcHv+Mbsq0aNGhVcFjvHQMo+/l7r6iFU\ntzFjxgS/M39+eKpZo9QZAIBmw5PIASBnoaGWxx57bMjbCF3s3HPPPVFlCU0A991tFipfaCJ6Cqnq\nCaTGk8gBAAAiEUABAABEYggPTSuvrv8UwzFVDFcAzYe2qDnRAwUAABCpdD1QoQmPkn/SY1WWCHzl\nypXBZbXuVvviiy+i85Jq1y1k165dwWUprzokrjwAAKgqXQAFAFmMHj1akyZNqsu2t2zZ4k0PPRz9\n8ccf96YvXbp0UNrIkSO96959993e9IULF3rTjxw54k0P8ZWxp6fHu+60adO86WYWladPvesJZMUQ\nHgAAQCQCKAAAgEgEUAAAAJGYA4VScM7p559/HpTe1tYW/E7s3Akp2/yJmPksUnhOixQu80svvRT8\njm+/NDrfnKHQfCGg7GiLGtdw2iJ6oAAAACJZva/6zKwhLivXr18fXJb6DpLp06cHl+UZodeqc62e\nm5BaLyc+cuTIBudcd/RGh2jatGnuk08+GZReh3pEby+kr6/Pm17rqi+kUY6pVEJXfc654d+2FWBm\neyVVn/txoqR99cqrgbRiPSc4506qV0bd3d2ut7c3ybZoi4o3nLaIITwALWHgSdXMeusZ8DcK6gnU\nD0N4AAAAkQigAAAAIjGEh1LYuHHjvpEjRzbK/JUh5V9rfkMe+ddRvfKfUIdthqzIMa8iUc/ENmzY\nsM/MaIsi8q+jQtsiAiiUQiPNXyH/8s83cc61RGBBPeuSF20R+UtiCA8AACBaHj1Q+/T7rcNSQV1+\nR916WXS3Y1VdyxFxi2qKcuQ5/AJkYmbtkl6RNF7SFknzXJM9wdPM2iS96py7shnra/3Pl/k3SZMl\nfSfpHyW9pCaqI8qh7gHU0c/jKLrLrVHKQDmGpehhCfIvrxsk7XbOzTGzNyVdJumdgsuUjJmNlvSp\npEmVpGas74WSRjjnzjez/5J0s4qrY9G/BfIvEEN4KJ2i53WQf6nn1cyU9G7l8/uSLi2wLMk55w45\n56ZI2l1Jasb6/p+kf618PiLpIRVUx6J/C+RfbP4EUABaSaekHyqff5R0QoFlyUPT1dc599/OuXVm\n9g+SRkraoCarI8qhiACqEa5eG6EMEuUA8rZP0rjK53FqjLmQ9dSU9TWzqyT9k6Qr1T8PqunqiMaX\newBVdJdbo5RBohyxzKzdzN40s81m9oJlfVlh9vwvN7PdZra28mdyjnm3mdkblc+574ej8i9sPySw\nRtKsyueZkj4osCx5aLr6mtnJkv5Z0t85535SAXWkLaItkhjCQ7lUJ8SeI6lD/ZNF87bMOXdR5c+X\neWRYmRi8Qb/XN9f94MlfKmA/JPKipD+b2RZJ+9V/8m1mzVjfmyR1SfpPM1srqU3515G2qF9Lt0W5\nBFBFR+sDylH4lXPR0XugHIXvlyFqhAmxc81snZmtzuv/q+iJwZ78pQL2QwrOuT7n3Bzn3BTn3I3N\neru7c+7Myt9NV1/n3L84584ccNJcXkAdaYv6tXRblFcPVCNE61WFRatFR+81yiGVo0eh6AmxOyQ9\n4Jz7i/qvgC/OOf8q9gNQLH6D/Vp6P+QVQDVCtF5VWLRadPReoxxSOXoUip4Qu1/Se5XPX0v6U875\nV7EfgGLxG+zX0vshrwCq6Ci1qlGi9ir2S5yiJ8TeJanHzI6TdLakrTnnX8V+AIrFb7BfS++HvAKo\noqPUqkaJ2qvYL3GKnhD7lKS/qv9Jz39zzn2Rc/5V7AegWPwG+7X0frA85tuZ2c2SznPO3WZm/yHp\nCefce8f6Xh3KsUTSV5JekLRJUk8RB56Z/Y9z7syi98uAcjTEfgEAoCzy6oEqOkqtapSovYr9AgBA\nCeXSAwUAANBMeJAmAABAJAIoAACASARQAAAAkQigAAAAIhFAAQAARCKAAgAAiEQABQAAEOn/AfOv\n9NTZUZ6TAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f4a744dda90>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "subimages = segment_image(image)\n",
    "f, axes = plt.subplots(1, len(subimages), figsize=(10, 3))\n",
    "for i in range(len(subimages)):\n",
    "    axes[i].imshow(subimages[i], cmap=\"gray\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.utils import check_random_state\n",
    "random_state = check_random_state(14)\n",
    "letters = list(\"ACBDEFGHIJKLMNOPQRSTUVWXYZ\")\n",
    "shear_values = np.arange(0, 0.5, 0.05)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def generate_sample(random_state=None):\n",
    "    random_state = check_random_state(random_state)\n",
    "    letter = random_state.choice(letters)\n",
    "    shear = random_state.choice(shear_values)\n",
    "    return create_captcha(letter, shear=shear, size=(20, 20)), letters.index(letter)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The target for this image is: 11\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n2ws7AAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f4a6f9c7a20>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "image, target = generate_sample(random_state)\n",
    "plt.imshow(image, cmap=\"gray\")\n",
    "print(\"The target for this image is: {0}\".format(target))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "dataset, targets = zip(*(generate_sample(random_state) for i in\n",
    "range(3000)))\n",
    "dataset = np.array(dataset, dtype='float')\n",
    "targets = np.array(targets)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.preprocessing import OneHotEncoder\n",
    "onehot = OneHotEncoder()\n",
    "y = onehot.fit_transform(targets.reshape(targets.shape[0],1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "y = y.todense()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from skimage.transform import resize"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/lab466/anaconda3/lib/python3.6/site-packages/skimage/transform/_warps.py:84: UserWarning: The default mode, 'constant', will be changed to 'reflect' in skimage 0.15.\n",
      "  warn(\"The default mode, 'constant', will be changed to 'reflect' in \"\n"
     ]
    }
   ],
   "source": [
    "dataset = np.array([resize(segment_image(sample)[0], (20, 20)) for\n",
    "sample in dataset])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "X = dataset.reshape((dataset.shape[0], dataset.shape[1] *\n",
    "dataset.shape[2]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/lab466/anaconda3/lib/python3.6/site-packages/sklearn/model_selection/_split.py:2026: FutureWarning: From version 0.21, test_size will always complement train_size unless both are specified.\n",
      "  FutureWarning)\n"
     ]
    }
   ],
   "source": [
    "#from sklearn.cross_validation import train_test_split\n",
    "from sklearn.model_selection import train_test_split\n",
    "X_train, X_test, y_train, y_test = \\\n",
    "train_test_split(X, y, train_size=0.9)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#sudo pip3 install git+https://github.com/pybrain/pybrain.git \n",
    "#此程序可以直接在ananconda2下运行\n",
    "from pybrain.datasets import SupervisedDataSet"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "training = SupervisedDataSet(X.shape[1], y.shape[1])\n",
    "for i in range(X_train.shape[0]):\n",
    "    training.addSample(X_train[i], y_train[i])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "testing = SupervisedDataSet(X.shape[1], y.shape[1])\n",
    "for i in range(X_test.shape[0]):\n",
    "    testing.addSample(X_test[i], y_test[i])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from pybrain.tools.shortcuts import buildNetwork\n",
    "net = buildNetwork(X.shape[1], 100, y.shape[1], bias=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from pybrain.supervised.trainers import BackpropTrainer\n",
    "trainer = BackpropTrainer(net, training, learningrate=0.01,\n",
    "weightdecay=0.01)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "trainer.trainEpochs(epochs=20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "predictions = trainer.testOnClassData(dataset=testing)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.metrics import f1_score\n",
    "#print(\"F-score: {0:.2f}\".format(f1_score(predictions, y_test.argmax(axis=1))))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "             precision    recall  f1-score   support\n",
      "\n",
      "          0       1.00      1.00      1.00        13\n",
      "          1       0.76      1.00      0.87        13\n",
      "          2       1.00      0.67      0.80        12\n",
      "          3       1.00      0.89      0.94         9\n",
      "          4       0.45      1.00      0.62         9\n",
      "          5       0.00      0.00      0.00        10\n",
      "          6       1.00      0.80      0.89         5\n",
      "          7       1.00      1.00      1.00        20\n",
      "          8       0.41      0.83      0.55        18\n",
      "          9       0.00      0.00      0.00         6\n",
      "         10       1.00      0.93      0.97        15\n",
      "         11       0.00      0.00      0.00         8\n",
      "         12       1.00      0.90      0.95        10\n",
      "         13       0.79      1.00      0.88        22\n",
      "         14       0.64      0.82      0.72        11\n",
      "         15       0.72      1.00      0.84        21\n",
      "         16       0.00      0.00      0.00         6\n",
      "         17       1.00      0.69      0.82        13\n",
      "         18       1.00      1.00      1.00        14\n",
      "         19       1.00      1.00      1.00         9\n",
      "         20       0.00      0.00      0.00         7\n",
      "         21       1.00      0.56      0.71         9\n",
      "         22       0.93      1.00      0.96        13\n",
      "         23       0.86      0.86      0.86         7\n",
      "         24       0.88      1.00      0.93         7\n",
      "         25       1.00      1.00      1.00        13\n",
      "\n",
      "avg / total       0.76      0.80      0.76       300\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/lab466/anaconda3/lib/python3.6/site-packages/sklearn/metrics/classification.py:1135: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples.\n",
      "  'precision', 'predicted', average, warn_for)\n"
     ]
    }
   ],
   "source": [
    "from sklearn.metrics import classification_report\n",
    "print(classification_report(y_test.argmax(axis=1), predictions))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def predict_captcha(captcha_image, neural_network):\n",
    "    subimages = segment_image(captcha_image)\n",
    "    predicted_word = \"\"\n",
    "    for subimage in subimages:\n",
    "        subimage = resize(subimage, (20, 20))\n",
    "        outputs = net.activate(subimage.flatten())\n",
    "        prediction = np.argmax(outputs)\n",
    "        predicted_word += letters[prediction]\n",
    "    return predicted_word"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "EWNW\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/lab466/anaconda3/lib/python3.6/site-packages/skimage/transform/_warps.py:84: UserWarning: The default mode, 'constant', will be changed to 'reflect' in skimage 0.15.\n",
      "  warn(\"The default mode, 'constant', will be changed to 'reflect' in \"\n"
     ]
    }
   ],
   "source": [
    "word = \"GENE\"\n",
    "captcha = create_captcha(word, shear=0.2)\n",
    "print(predict_captcha(captcha, net))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def test_prediction(word, net, shear=0.2):\n",
    "    captcha = create_captcha(word, shear=shear)\n",
    "    prediction = predict_captcha(captcha, net)\n",
    "    prediction = prediction[:4]\n",
    "    return word == prediction, word, prediction"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from nltk.corpus import words"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "valid_words = [word.upper() for word in words.words() if len(word) == 4]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/lab466/anaconda3/lib/python3.6/site-packages/skimage/transform/_warps.py:84: UserWarning: The default mode, 'constant', will be changed to 'reflect' in skimage 0.15.\n",
      "  warn(\"The default mode, 'constant', will be changed to 'reflect' in \"\n"
     ]
    }
   ],
   "source": [
    "num_correct = 0\n",
    "num_incorrect = 0\n",
    "for word in valid_words:\n",
    "    correct, word, prediction = test_prediction(word, net, shear=0.2)\n",
    "    if correct:\n",
    "        num_correct += 1\n",
    "    else:\n",
    "        num_incorrect += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"Number correct is {0}\".format(num_correct))\n",
    "print(\"Number incorrect is {0}\".format(num_incorrect))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.metrics import confusion_matrix\n",
    "cm = confusion_matrix(np.argmax(y_test, axis=1), predictions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(20,20))\n",
    "plt.imshow(cm, cmap=\"Blues\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from nltk.metrics import edit_distance\n",
    "steps = edit_distance(\"STEP\", \"STOP\")\n",
    "print(\"The number of steps needed is: {0}\".format(steps))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def compute_distance(prediction, word):\n",
    "    return len(prediction) - sum(prediction[i] == word[i] for i in range(len(prediction)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from operator import itemgetter\n",
    "def improved_prediction(word, net, dictionary, shear=0.2):\n",
    "    captcha = create_captcha(word, shear=shear)\n",
    "    prediction = predict_captcha(captcha, net)\n",
    "    prediction = prediction[:4]\n",
    "    if prediction not in dictionary:\n",
    "        distances = sorted([(word, compute_distance(prediction, word))\n",
    "                            for word in dictionary],\n",
    "                           key=itemgetter(1))\n",
    "        best_word = distances[0]\n",
    "        prediction = best_word[0]\n",
    "    return word == prediction, word, prediction"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "num_correct = 0\n",
    "num_incorrect = 0\n",
    "for word in valid_words:\n",
    "    correct, word, prediction = improved_prediction (word, net, valid_words, shear=0.2)\n",
    "    if correct:\n",
    "        num_correct += 1\n",
    "    else:\n",
    "        num_incorrect += 1\n",
    "print(\"Number correct is {0}\".format(num_correct))\n",
    "print(\"Number incorrect is {0}\".format(num_incorrect))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
